﻿namespace JunFan.Domain
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Globalization;
    using System.Text.RegularExpressions;
    using Repositories;

    /// <summary>
    /// Board is the Aggregate for items.
    /// </summary>
    public class Board
    {
        private readonly IRepository<Item> _itemRepository;

        public Board()
        {
            _itemRepository = new ItemRepository();
        }

        public Board(IRepository<Item> itemRepository)
        {
            _itemRepository = itemRepository;
        }

        public Item AddItem(Item item)
        {
            if (ItemExists(item))
            {
                throw new BusinessRuleException("Id", string.Format(BusinessRulesMessages.ItemIdShouldBeUniqueErrorMessage, item.Id));
            }

            if (item.CreatedOn == default(DateTime))
            {
                item.CreatedOn = DateTime.Today;
            }

            return _itemRepository.Create(item);
        }

        public bool ItemExists(Item item)
        {
            return _itemRepository.Exists(item);
        }

        public Item CompleteItem(int itemId)
        {
            return CompleteItem(itemId, DateTime.Today);
        }

        public Item CompleteItem(int itemId, DateTime completeDate)
        {
            var item = GetItem(itemId);

            item.CompletedOn = completeDate;

            _itemRepository.Update(item);

            return item;
        }

        public Item StartItem(int itemId)
        {
            return StartItem(itemId, DateTime.Today);
        }

        public Item StartItem(int itemId, DateTime startDate)
        {
            Item item = GetItem(itemId);

            if (item.IsCompleted())
            {
                throw new BusinessRuleException("ItemId", BusinessRulesMessages.StartCompletedItemErrorMessage);
            }

            item.StartedOn = startDate;

            _itemRepository.Update(item);

            return item;
        }

        #region Get items
        public IEnumerable<Item> GetInProgressItems()
        {
            return _itemRepository.ReadAll(item => item.IsInProgress());
        }

        public IEnumerable<Item> GetCompletedItems()
        {
            return _itemRepository.ReadAll(item => item.IsCompleted());
        }

        public IEnumerable<Item> GetBacklogItems()
        {
            return _itemRepository.ReadAll(item => item.IsInBacklog());
        }
        #endregion Get items

        private Item GetItem(int itemId)
        {
            Item item = _itemRepository.Read(itemId);

            if (item == null)
            {
                string callerMethod = new StackTrace().GetFrame(1).GetMethod().Name;

                string action = Regex.Replace(callerMethod, ".[A-Z]", m => m.ToString()[0] + " " + char.ToLower(m.ToString()[1]));

                throw new WrongArgumentException("ItemId", itemId.ToString(CultureInfo.InvariantCulture), action, string.Format("There isn't an Item with id '{0}'.", itemId));
            }

            return item;
        }
    }
}